package com.github.cyf.mail;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StreamUtils;
import javax.mail.*;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author chenyifan
 * @create 2025-03-09 12:47
 */
@Component
@Slf4j
public class MailService {

    @Autowired
    private MailProperties mailProperties;

    @Autowired
    private JavaMailSender mailSender;

    public void sendMessage(String to, String subject, String content, List<File> fileList) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(mailProperties.getUsername());
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content);
            helper.setSentDate(new Date());
            if (!CollectionUtils.isEmpty(fileList)) {
                for (File file : fileList){
                    helper.addAttachment(file.getName(), file);
                }
            }
        } catch (MessagingException e) {
            log.error("发送邮件失败", e);
            throw new RuntimeException(e);
        }
        mailSender.send(message);
    }

    public MailInfo readMessage(Message message, String fileSaveDir) throws MessagingException, IOException {
        MailInfo mailInfo = new MailInfo();
        mailInfo.setSubject(message.getSubject());
        mailInfo.setSendUser(extractEmail(message.getFrom()[0].toString()));
        mailInfo.setSendTime(LocalDateTime.ofInstant(message.getSentDate().toInstant(), ZoneId.systemDefault()));
        Object content = message.getContent();
        // 如果邮件是多部分内容
        if (content instanceof MimeMultipart) {
            MimeMultipart multipart = (MimeMultipart) content;
            List<File> files = new ArrayList<>();
            mailInfo.setFileList(files);
            // 遍历每个部分
            for (int i = 0; i < multipart.getCount(); i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                // 检查是否是附件
                if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                    // 获取附件文件名
                    String fileName = MimeUtility.decodeText(bodyPart.getFileName());
                    log.info("发现附件: {}", fileName);
                    // 保存附件到临时目录
                    File attachmentFile = Paths.get(fileSaveDir, fileName).toFile();
                    if (!attachmentFile.getParentFile().exists()) {
                        attachmentFile.getParentFile().mkdirs();
                    }
                    // 读取附件内容
                    try (FileOutputStream os = new FileOutputStream(attachmentFile);
                         InputStream is = bodyPart.getInputStream()) {
                        StreamUtils.copy(is, os);
                    }
                    files.add(attachmentFile);
                    log.info("附件保存到，{}", attachmentFile.getAbsolutePath());
                } else if (bodyPart.isMimeType("text/plain")) {
                    // 获取纯文本内容
                    String textContent = (String) bodyPart.getContent();
                    mailInfo.setText(textContent);
                    log.info("读取到邮件内容: {}", textContent);
                } else if (bodyPart.isMimeType("text/html")) {
                    // 获取 HTML 内容
                    String htmlContent = (String) bodyPart.getContent();
                    mailInfo.setHtml(htmlContent);
                    log.info("读取到邮件内容: {}", htmlContent);
                }
            }
        } else if (content instanceof String) {
            String textContent = (String) content;
            // 如果邮件是简单文本内容
            mailInfo.setText(textContent);
            log.info("读取到邮件内容: {}", textContent);
        } else {
            log.info("邮件内容类型未知");
        }
        return mailInfo;
    }

    public void handlerMessages(Consumer<List<Message>> consumer) {
        Properties properties = new Properties();
        properties.put("mail.store.protocol", "imaps");
        properties.put("mail.imaps.host", "imap.qq.com");
        properties.put("mail.imaps.port", "993");
        properties.put("mail.imaps.ssl.enable", "true");

        Session emailSession = Session.getDefaultInstance(properties);
        Store store = null;
        Folder inbox = null;
        try {
            store = emailSession.getStore("imaps");
            store.connect("imap.qq.com", mailProperties.getUsername(), mailProperties.getPassword());

            // 从邮件存储（Store）中获取名为 "INBOX" 的文件夹。
            //"INBOX" 是邮箱中默认的收件箱文件夹，所有收到的邮件通常都会存储在这里。
            inbox = store.getFolder("INBOX");
            inbox.open(Folder.READ_ONLY);

            // 处理邮件
            consumer.accept(Arrays.asList(inbox.getMessages()));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inbox != null) {
                    inbox.close(false);
                }
                if (store != null) {
                    store.close();
                }
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }

    private static final Pattern EMAIL_EXTRACT_PATTERN = Pattern.compile("<([^>]+)>");

    private String extractEmail(String input) {
        // 正则表达式匹配 < > 中的邮箱地址
        Matcher matcher = EMAIL_EXTRACT_PATTERN.matcher(input);
        if (matcher.find()) {
            return matcher.group(1); // 返回匹配的邮箱地址
        }
        return null; // 如果没有匹配到，返回 null
    }
}
